#include <QtGui>
#include <QtNetwork>
#include "MainWindow.h"
#include "../shared/Player.h"
#include "../shared/Bullet.h"
#include "../shared/Map.h"
#include "LoginWindow.h"
#include "AboutWindow.h"
#include <iostream>


MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
{
    setupUi(this);

    connect(actionLogin,  SIGNAL(triggered()), this, SLOT(Login()));
    connect(actionLogout, SIGNAL(triggered()), this, SLOT(Logout()));
    connect(actionQuit,   SIGNAL(triggered()), this, SLOT(close()));
    connect(actionAbout,  SIGNAL(triggered()), this, SLOT(About()));


    tcpSocket = new QTcpSocket(this);

    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readData()));
    connect(tcpSocket, SIGNAL(connected()), this, SLOT(connectedToServer()));
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnectFromServer()));
    connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));

}


MainWindow::~MainWindow()
{
    delete tcpSocket;
}


// wywolywana po wcisnieciu Gra -> Logowanie
void MainWindow::Login()
{
    LoginWindow *loginWin = new LoginWindow;
    connect(loginWin, SIGNAL(connectToHost(QString, int, QString)), this, SLOT(connectToServer(QString, int, QString)));
    loginWin->show();
}


// proba laczenia sie z serwerem
void MainWindow::connectToServer(QString ip, int port, QString _nick)
{
    tcpSocket->abort();
    blockSize = 0;

    tcpSocket->connectToHost(ip, port);

    nick = _nick;
}


// wywolywana w momencie polaczenia z serwerem
void MainWindow::connectedToServer()
{

 //   if (tcpSocket->peerPort() == 0)
   //     statsLabel->setText(tr("Niezalogowany"));
   // else
        statsLabel->setText(tr("Połączono z serwerem %1 : %2").arg(tcpSocket->peerAddress().toString()).arg(tcpSocket->peerPort()));

    QTimer *timer = new QTimer(this);
    timer->setInterval(65);
    timer->start();

    connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));

}


// wysylaj paczke danych
void MainWindow::sendData()
{

    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);

    out << (quint16) 0;
    out << nick;
    out << graphicsView->player->moveLeft;
    out << graphicsView->player->moveRight;
    out << graphicsView->player->moveUp;
    out << graphicsView->player->moveDown;
    out << graphicsView->player->shoot;
    if (graphicsView->player->shoot)
    {
        out << graphicsView->mouseX;
        out << graphicsView->mouseY;
        graphicsView->player->shoot = false;
    }


    out.device()->seek(0);

    out << (quint16) (data.size() - sizeof(quint16));

    tcpSocket->write(data);
}


// odbiera dane z serwera
void MainWindow::readData()
{

    QDataStream in(tcpSocket);
    in.setVersion(QDataStream::Qt_4_0);

    if (blockSize == 0)
    {
        if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
        {
            return;
        }

        in >> blockSize;
    }

    if (tcpSocket->bytesAvailable() < blockSize)
    {
        return;
    }


    QList<Bullet *>::iterator iterb;
    QList<Player *>::iterator iterp;
    int size;
    qreal posx, posy;
    int points, type;
    QString nic;

    // wyczysc ekran
    for (iterb = graphicsView->bulletsList->begin(); iterb != graphicsView->bulletsList->end(); ++iterb)
    {
        (*iterb)->setVisible(false);
    }
    for (iterp = graphicsView->playersList->begin(); iterp != graphicsView->playersList->end(); ++iterp)
    {
        (*iterp)->setVisible(false);
    }

    // wyczysc okno statystyk
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 5; j++)
        {
            tableWidget->setItem(j, i, new QTableWidgetItem(""));
        }

    in >> size;
    for (int i = 0; i < size; ++i)
    {
        in >> nic;
        tableWidget->setItem(i, 0, new QTableWidgetItem(nic));

        in >> posx;
        in >> posy;

        graphicsView->playersList->at(i)->setPos(posx, posy);
        graphicsView->playersList->at(i)->setVisible(true);

        in >> points;
        tableWidget->setItem(i, 1, new QTableWidgetItem(QString::number(points)));

        in >> points;
        tableWidget->setItem(i, 2, new QTableWidgetItem(QString::number(points)));
    }

    in >> size;
    for (int i = 0; i < size; ++i)
    {
        in >> posx;
        in >> posy;
        in >> type;

        if (type == 1)
        {
            graphicsView->bulletsList->at(i)->setPos(posx, posy);
            graphicsView->bulletsList->at(i)->setVisible(true);
        }
           else
            {
                if (i+15 < 30)
                {
                    graphicsView->bulletsList->at(15+i)->setPos(posx, posy);
                    graphicsView->bulletsList->at(15+i)->setVisible(true);
                }
else
                {
                    graphicsView->bulletsList->at(29)->setPos(posx, posy);
                    graphicsView->bulletsList->at(29)->setVisible(true);
                }


            }

    }

    blockSize = 0;
}


// wywolywana w momencie odlaczenia od serwera
void MainWindow::disconnectFromServer()
{
    tcpSocket->close();
    statsLabel->setText(tr("Odłączono od serwera"));

    // czysc tablice statystyk
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 5; j++)
        {
            tableWidget->setItem(j, i, new QTableWidgetItem(""));
        }
}

// w przypadku, gdy wystapil blad przy probie polaczenia
void MainWindow::displayError(QAbstractSocket::SocketError socketError)
{

    switch (socketError)
    {
    case QAbstractSocket::RemoteHostClosedError:
        break;
    case QAbstractSocket::HostNotFoundError:
        QMessageBox::information(this, tr("Client"), tr("Nie znaleziono hosta."));
        break;
    case QAbstractSocket::ConnectionRefusedError:
        QMessageBox::information(this, tr("Client"),
                                 tr("Połączenie nie powiodło się. Upewnij się, że serwer jest uruchomiony."));
        break;
    default:
        QMessageBox::information(this, tr("Client"),
                                 tr("Wystąpił następujący błąd : %1.").arg(tcpSocket->errorString()));
    }

}


// wywolywana po wcisnieciu Gra -> Wylogowanie
void MainWindow::Logout()
{
    tcpSocket->close();
    statsLabel->setText(tr("Wylogowano z serwera"));
}

// wywolywana po wcisnieciu Pomoc -> Informacje
void MainWindow::About()
{
    AboutWindow *aboutWin = new AboutWindow;
    aboutWin->show();
}
